package com.group2.operations.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.group2.operations.common.api.ApiResult;
import com.group2.operations.config.AliyunConfig;
import com.group2.operations.model.Contract;
import com.group2.operations.model.ProcessState;
import com.group2.operations.model.User;
import com.group2.operations.model.dto.ProcessDTO;
import com.group2.operations.model.dto.ProcessStateDTO;
import com.group2.operations.model.vo.UserInfoVO;
import com.group2.operations.service.ContractService;
import com.group2.operations.service.FlowService;
import com.group2.operations.service.UserService;
import io.swagger.annotations.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.flowable.engine.common.impl.identity.Authentication;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private FlowService flowService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private AliyunConfig aliyunConfig;

    /**
     * 用户登录
     * @param user 用户
     * @return
     */
    @PostMapping("/login")
    @ApiOperation("登录")
    @ApiImplicitParam(name = "user", dataTypeClass = User.class, value = "用户对象", required = true)
    public ApiResult login(@RequestBody @Valid User user) {
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPwd());
        //封装SessionID
        Map map = new HashMap();
        //执行登陆方法
        try {
            subject.login(token);
            map.put("token", subject.getSession().getId().toString());
            if(subject.hasRole("normal")) {
                map.put("role", "normal");
            }
            else if(subject.hasRole("agent")) {
                map.put("role", "agent");
            }
        } catch (UnknownAccountException e) {
            return ApiResult.failed("用户名或密码错误");
        } catch (IncorrectCredentialsException e) {
            return ApiResult.failed("用户名或密码错误");
        }

        return ApiResult.success(map, "登录成功");
    }

    /**
     * 用户注册
     * @param user  用户对象
     * @return
     */
    @PostMapping("/register")
    @ApiOperation("用户注册")
    @ApiImplicitParam(name = "user", dataTypeClass = User.class, value = "用户对象", required = true)
    public ApiResult register(@RequestBody @Valid User user) {
        return userService.insertUser(user);
    }

    /**
     * 更新用户个人信息
     * @param vo
     * @return
     */
    @PutMapping("/info")
    @RequiresPermissions("normal:update_info")
    @ApiOperation("更新用户个人信息")
    @ApiImplicitParam(name = "vo", dataTypeClass = UserInfoVO.class, value = "个人信息对象", required = true)
    public ApiResult updateInfo(@RequestBody @Valid UserInfoVO vo) {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户名
        String username = user.getName();

//        if(subject.isPermitted("normal:update_info")) {
//            return userService.updateUserInfo(vo, username);
//        }
//        return null;
        return userService.updateUserInfo(vo, username);
    }

    /**
     * 获取用户个人信息
     * @return
     */
    @GetMapping("/info")
    @RequiresPermissions("normal:get_info")
    @ApiOperation("获取用户个人信息")
    public ApiResult getInfo() {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户名
        String username = user.getName();

//        if(subject.isPermitted("normal:get_info")) {
//            return ApiResult.success(userService.getUserInfo(username));
//        }
//        return null;
        return ApiResult.success(userService.getUserInfo(username));
    }

    /**
     * 申请成为代理商，发起流程
     * @return
     */
    @PostMapping("/apply")
    @RequiresPermissions("normal:contract")
    @ApiOperation("申请成为代理商，发起流程")
    public ApiResult apply() {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取最新的用户
        User userNow = userService.queryUserByName(user.getName());
        //判断用户是否填写个人信息
        if(!userNow.isInfoUpdated()) {
            return ApiResult.failed("申请失败，请先填写个人信息");
        }
        //判断用户是否有尚未结束的申请
        if(flowService.hasApplied(userNow.getName())) {
            return ApiResult.failed("申请失败，请等现有申请流程结束后再次申请");
        }
        //List<Contract>
        //组织传递的参数
        Map<String, Object> variables = new HashMap<>();
        variables.put("name", userNow.getReal());
        variables.put("number", userNow.getNumber());
        variables.put("phone", userNow.getPhone());
        variables.put("email", userNow.getEmail());

        //设置流程发起人
        Authentication.setAuthenticatedUserId(userNow.getName());
        //开启流程
        ProcessInstance process = flowService.startProcess(variables, "ApplyAgentProcess");
        Authentication.setAuthenticatedUserId(null);


        System.out.println(process.getId());

        //完成流程的第一个任务
        flowService.completeFirstTask(user.getName(), "申请成为代理商", process.getId(), process.getProcessDefinitionName(), process.getStartTime());

        return Objects.isNull(process) ? ApiResult.failed("申请失败") : ApiResult.success("提交申请成功，请等待审核");
    }

    @GetMapping("/workflow")
    @RequiresRoles(value = {"normal", "agent"}, logical = Logical.OR)
    @ApiOperation("查询用户发起的所有流程")
    public ApiResult listWorkFlow() {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户名
        String username = user.getName();
        //获取流程实例列表
        List<HistoricProcessInstance> processes = flowService.queryProcessByUserName(username);

        List<ProcessDTO> processInfos = new ArrayList<>();

        for(HistoricProcessInstance process : processes) {
            ProcessDTO proccessInfo = ProcessDTO.builder()
                    .id(process.getId())
                    .name(process.getProcessDefinitionName())
                    .time(process.getStartTime().getTime())
                    .isFinished(flowService.isFinished(process.getId()))
                    .build();
            processInfos.add(proccessInfo);
            //System.out.println("id: " + process.getId() + " name: " + process.getProcessDefinitionName() + " startTime: " + process.getStartTime().getTime() + " finished: " + flowService.isFinished(process.getId()));
        }


        return ApiResult.success(processInfos);
    }

    @GetMapping("/workflow/{processId}")
    @RequiresRoles(value = {"normal", "agent"}, logical = Logical.OR)
    @ApiOperation("查询某一个流程经历的所有历史事件")
    public ApiResult processDetail(@PathVariable String processId) {
        List<ProcessStateDTO> list = new ArrayList<>();
        ProcessState states = flowService.getHistory(processId);
        if(states.getState1() != null) {
            //map.put(states.getState1(), states.getTime1().getTime());
            list.add(new ProcessStateDTO(states.getState1(), states.getTime1().getTime()));
        }
        if(states.getState2() != null) {
            //map.put(states.getState2(), states.getTime2().getTime());
            list.add(new ProcessStateDTO(states.getState2(), states.getTime2().getTime()));
        }
        if(states.getState3() != null) {
            //map.put(states.getState3(), states.getTime3().getTime());
            list.add(new ProcessStateDTO(states.getState3(), states.getTime3().getTime()));
        }
        if(states.getState4() != null) {
            //map.put(states.getState1(), states.getTime4().getTime());
            list.add(new ProcessStateDTO(states.getState4(), states.getTime4().getTime()));
        }
        if(states.getState5() != null) {
            //map.put(states.getState5(), states.getTime5().getTime());
            list.add(new ProcessStateDTO(states.getState5(), states.getTime5().getTime()));
        }
        return ApiResult.success(list);
    }

    @GetMapping("/contract")
    @RequiresPermissions("normal:contract")
    @ApiOperation("列出自己所有的合同")
    public ApiResult listContracts() {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户ID
        int uid = user.getId();

        List<Contract> contracts = contractService.listContracts(uid);

        return ApiResult.success(contracts);
    }

    @GetMapping("/contract/download/{contractId}")
    @ApiOperation("下载合同文件")
    public void downloadContract(@PathVariable("contractId") int cid, HttpServletResponse res) throws IOException {
        //查询数据库获取文件url
        String url = contractService.queryContractNameById(cid);
        //获取文件URL
        String decodeUrl = URLDecoder.decode(url, "utf-8");
        //获取文件名
        String fileName = decodeUrl.split(aliyunConfig.getUrlPrefix())[1];
        res.setContentType("application/x-download;charset=GBK");
        //通知浏览器以附件形式下载
        res.setHeader("Content-Disposition",
                "attachment;filename=" + new String(fileName.getBytes(), "ISO-8859-1"));
        contractService.exportOssFile(res.getOutputStream(), fileName);
    }

    @PostMapping("/contract/sign/{contractId}")
    @RequiresPermissions("normal:contract")
    @ApiOperation("签署指定的合同")
    public ApiResult signContract(@PathVariable("contractId") int cid) {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户名
        String username = user.getName();

        return contractService.actContract(username, cid, "通过");
    }

    @PostMapping("/contract/reject/{contractId}")
    @RequiresPermissions("normal:contract")
    @ApiOperation("驳回指定的合同")
    public ApiResult rejectContract(@PathVariable("contractId") int cid) {
        Subject subject = SecurityUtils.getSubject();
        //获取用户
        User user = (User) subject.getPrincipal();
        //获取用户名
        String username = user.getName();
        return contractService.actContract(username, cid, "驳回");
    }

//    /**
//     * 权限测试方法
//     * @return
//     */
//    @PostMapping("/add")
//    @ApiOperation("添加")
//    public ApiResult add() {
//        Subject subject = SecurityUtils.getSubject();
//        if(subject.isPermitted("test1")) {
//            return ApiResult.success("添加成功");
//        }
//        return null;
//    }
}
